home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / muds / pennmush.000 / pennmush-1.50-p8-linux.tar / pennmush / match.c < prev    next >
C/C++ Source or Header  |  1993-04-15  |  10KB  |  460 lines

  1. /* match.c */
  2. /* Routines for parsing arguments */
  3.  
  4. #include "copyright.h"
  5. #include <ctype.h>
  6. #include <string.h>
  7. #include "config.h"
  8. #include "db.h"
  9. #include "externs.h"
  10. #include "globals.h"
  11. #include "match.h"
  12.  
  13. static dbref exact_match = NOTHING;    /* holds result of exact match */
  14. static int check_keys = 0;    /* if non-zero, check for keys */
  15. static dbref last_match = NOTHING;    /* holds result of last match */
  16. static int match_count;        /* holds total number of inexact matches */
  17. static dbref match_who;        /* player who is being matched around */
  18. static const char *match_name;    /* name to match */
  19. static int preferred_type = NOTYPE;    /* preferred type */
  20.  
  21. #ifdef DO_GLOBALS
  22. static int global = 0;          /* when 0 -- normal match */
  23. /*      1 -- global match */
  24. /*      2 -- remote match */
  25. #endif
  26.  
  27. char const *nomatch_message="I don't see that here.";
  28. char const *ambiguous_message="I don't know which one you mean!";
  29.  
  30. /*
  31.  * check a list for objects that are prefix's for string, && are controlled
  32.  * || link_ok
  33.  */
  34. dbref pref_match(player, list, string)
  35.      dbref player;
  36.      dbref list;
  37.      const char *string;
  38. {
  39.     dbref lmatch = NOTHING;
  40.     int mlen = 0;
  41.     
  42.     while (list != NOTHING) {
  43.     if (string_prefix(string, db[list].name) && Puppet(list) &&
  44.         controls(player, list)) {
  45.         if (strlen(db[list].name) > mlen) {
  46.         lmatch = list;
  47.         mlen = strlen(db[list].name);
  48.         }
  49.     }
  50.     list = db[list].next;
  51.     }
  52.     return (lmatch);
  53. }
  54.  
  55. void init_match(player, name, type)
  56.      dbref player;
  57.      const char *name;
  58.      int type;
  59. {
  60.     exact_match = last_match = NOTHING;
  61.     match_count = 0;
  62.     match_who = player;
  63.     match_name = name;
  64.     check_keys = 0;
  65.     preferred_type = type;
  66. #ifdef DO_GLOBALS
  67.     global = NORMAL_MATCH;
  68. #endif
  69. }
  70.  
  71. void init_match_check_keys(player, name, type)
  72.      dbref player;
  73.      const char *name;
  74.      int type;
  75. {
  76.     init_match(player, name, type);
  77.     check_keys = 1;
  78. }
  79.  
  80. #ifdef DO_GLOBALS
  81. void init_match_global(player, name, type)
  82.      dbref player;
  83.      const char *name;
  84.      int type;
  85. {
  86.     init_match(player, name, type);
  87.     global = GLOBAL_MATCH;
  88. }
  89.  
  90. void init_match_global_check_keys(player, name, type)
  91.      dbref player;
  92.      const char *name;
  93.      int type;
  94. {
  95.     init_match_global(player, name, type);
  96.     check_keys = 1;
  97. }
  98.  
  99. void init_match_remote(location, name, type)
  100.      dbref location;
  101.      const char *name;
  102.      int type;
  103. {
  104.     exact_match = last_match = NOTHING;
  105.     match_count = 0;
  106.     match_who = location;
  107.     match_name = name;
  108.     check_keys = 0;
  109.     preferred_type = type;
  110.     global = REMOTE_MATCH;
  111. }
  112.  
  113. void init_match_remote_check_keys(location, name, type)
  114.      dbref location;
  115.      const char *name;
  116.      int type;
  117. {
  118.     init_match_remote(location, name, type);
  119.     check_keys = 1;
  120. }
  121. #endif
  122.  
  123. static dbref choose_thing(thing1, thing2)
  124.      dbref thing1;
  125.      dbref thing2;
  126. {
  127.     int has1;
  128.     int has2;
  129.     if (thing1 == NOTHING) {
  130.     return thing2;
  131.     } else if (thing2 == NOTHING) {
  132.     return thing1;
  133.     }
  134.     if (preferred_type != NOTYPE) {
  135.     if (Typeof(thing1) == preferred_type) {
  136.         if (Typeof(thing2) != preferred_type) {
  137.         return thing1;
  138.         }
  139.     } else if (Typeof(thing2) == preferred_type) {
  140.         return thing2;
  141.     }
  142.     }
  143.     if (check_keys) {
  144.     has1 = could_doit(match_who, thing1);
  145.     has2 = could_doit(match_who, thing2);
  146.     
  147.     if (has1 && !has2) {
  148.         return thing1;
  149.     } else if (has2 && !has1) {
  150.         return thing2;
  151.     }
  152.     /* else fall through */
  153.     }
  154.     return (random() % 2 ? thing1 : thing2);
  155. }
  156.  
  157. void match_player()
  158. {
  159.     dbref match;
  160.     const char *p;
  161.     
  162.     extern dbref short_page();    /* in bsd.c */
  163.     
  164.     if (*match_name == LOOKUP_TOKEN) {
  165.     for (p = match_name + 1; isspace(*p); p++) ;
  166.     if ((match = lookup_player(p)) != NOTHING) {
  167.         exact_match = match;
  168.     } else {
  169.         /* try a partial match on a connected player, 2.0 style */
  170.         match = short_page(p);
  171.         if ((match != NOTHING) && (match != AMBIGUOUS))
  172.         exact_match = match;
  173.     }
  174.     }
  175. }
  176.  
  177. /* returns nnn if name = #nnn, else NOTHING */
  178. static dbref absolute_name()
  179. {
  180.     dbref match;
  181.     if (*match_name == NUMBER_TOKEN) {
  182.     match = parse_dbref(match_name + 1);
  183.     if (match < 0 || match >= db_top) {
  184.         return NOTHING;
  185.     } else {
  186.         return match;
  187.     }
  188.     } else {
  189.     return NOTHING;
  190.     }
  191. }
  192.  
  193. void match_absolute()
  194. {
  195.     dbref match;
  196.     if ((match = absolute_name()) != NOTHING) {
  197.     exact_match = match;
  198.     }
  199. }
  200.  
  201. void match_controlled_absolute()
  202. {
  203.     /* this exists to provide mortals with a way of controlling their objects
  204.      * via dbref number, if they own the object. Unlike match_absolute(),
  205.      * here, a control check is done.
  206.      * alternatively, if the two objects are "nearby", the absolute
  207.      * match also succeeds. This allows players to get out of situations
  208.      * where there are several identically-named objects, and the game
  209.      * refuses to allow them to pick one by anything other than number.
  210.      */
  211.     dbref match;
  212.     if (((match = absolute_name()) != NOTHING) && 
  213.     (controls(match_who, match) || nearby(match_who, match))) {
  214.     exact_match = match;
  215.     }
  216. }
  217.  
  218. void match_me()
  219. {
  220.     if (!strcasecmp(match_name, "me")) {
  221.     exact_match = match_who;
  222.     }
  223. }
  224.  
  225. void match_here()
  226. {
  227.     if (!strcasecmp(match_name, "here")
  228.     && db[match_who].location != NOTHING) {
  229.     exact_match = db[match_who].location;
  230.     }
  231. }
  232.  
  233. static void match_list(first)
  234.      dbref first;
  235. {
  236.     dbref absolute;
  237.     absolute = absolute_name();
  238.     if (!controls(match_who, absolute))
  239.     absolute = NOTHING;
  240.     
  241.     DOLIST(first, first) {
  242.     Access(first);
  243.     if (first == absolute) {
  244.         exact_match = first;
  245.         return;
  246.     } else if (!strcasecmp(db[first].name, match_name)) {
  247.         /* if there are multiple exact matches, randomly choose one */
  248.         exact_match = choose_thing(exact_match, first);
  249.     } else if (string_match(db[first].name, match_name)) {
  250.         last_match = first;
  251.         match_count++;
  252.     }
  253.     }
  254. }
  255.  
  256. void match_possession()
  257. {
  258.     match_list(db[match_who].contents);
  259. }
  260.  
  261. void match_neighbor()
  262. {
  263.     dbref loc;
  264.     loc = Location(match_who);
  265.     if (GoodObject(loc)) 
  266.     match_list(Contents(loc));
  267. }
  268.  
  269. #ifdef DO_GLOBALS
  270. void match_remote_contents()
  271. {
  272.     if (match_who != NOTHING)
  273.     match_list(db[match_who].contents);
  274. }
  275. #endif
  276.  
  277. void match_container()
  278. {
  279.     if (GoodObject(Location(match_who)))
  280.     match_list(Location(match_who));
  281. }
  282.  
  283. void match_exit()
  284. {
  285.     dbref loc;
  286.     dbref exit_tmp;
  287.     dbref absolute;
  288.     const char *match;
  289.     const char *p;
  290. #ifdef DO_GLOBALS
  291.     switch (global) {
  292.       case NORMAL_MATCH:
  293.     loc = db[match_who].location;
  294.     break;
  295.       case GLOBAL_MATCH:
  296.     loc = MASTER_ROOM;
  297.     break;
  298.       case REMOTE_MATCH:
  299.     loc = match_who;
  300.     break;
  301.     }
  302. #else
  303.     loc = db[match_who].location;
  304. #endif
  305.     if (GoodObject(loc)) {
  306.     if (Typeof(loc) != TYPE_ROOM)
  307.         return;
  308.     absolute = absolute_name();
  309.     if (!controls(match_who, absolute))
  310.         absolute = NOTHING;
  311.     
  312.     DOLIST(exit_tmp, db[loc].exits) {
  313.         Access(exit_tmp);
  314.         if (exit_tmp == absolute) {
  315.         exact_match = exit_tmp;
  316.         } else {
  317.         match = db[exit_tmp].name;
  318.         while (*match) {
  319.             /* check out this one */
  320.             for (p = match_name;
  321.              (*p
  322.               && DOWNCASE(*p) == DOWNCASE(*match)
  323.               && *match != EXIT_DELIMITER);
  324.              p++, match++) ;
  325.             /* did we get it? */
  326.             if (*p == '\0') {
  327.             /* make sure there's nothing afterwards */
  328.             while (isspace(*match))
  329.                 match++;
  330.             if (*match == '\0' || *match == EXIT_DELIMITER) {
  331.                 /* we got it */
  332.                 exact_match = choose_thing(exact_match, exit_tmp);
  333.                 goto next_exit;    /* got this match */
  334.             }
  335.             }
  336.             /* we didn't get it, find next match */
  337.             while (*match && *match++ != EXIT_DELIMITER) ;
  338.             while (isspace(*match))
  339.             match++;
  340.         }
  341.         }
  342.       next_exit:
  343.         ;
  344.     }
  345.     }
  346. }
  347.  
  348. void match_everything()    
  349. {
  350.     match_me();
  351.     match_here();
  352.     match_absolute();
  353.     match_player();
  354.     if (match_result() == NOTHING) {
  355.     match_neighbor();
  356.     match_possession();
  357.     match_exit();
  358.     }
  359. }
  360.  
  361. void match_nearby()
  362. {
  363.     match_me();
  364.     match_here();
  365.     if (Long_Fingers(match_who)) {
  366.     match_absolute();
  367.     match_player();
  368.     } else
  369.     match_controlled_absolute();
  370.     if (match_result() == NOTHING) {
  371.     match_neighbor();
  372.     match_possession();
  373.     match_exit();
  374.     }
  375. }
  376.  
  377. void match_near_things()
  378. {
  379.     match_me();
  380.     if (Long_Fingers(match_who)) {
  381.     match_absolute();
  382.     match_player();
  383.     } else
  384.     match_controlled_absolute();
  385.     if (match_result() == NOTHING) {
  386.     match_neighbor();
  387.     match_possession();
  388.     }
  389. }
  390.  
  391.  
  392. #ifdef DO_GLOBALS
  393. void match_remote()
  394. {
  395.     match_exit();
  396.     match_remote_contents();
  397.     match_absolute();
  398.     match_player();
  399. }
  400. #endif
  401.  
  402. dbref match_result()
  403. {
  404.     if (exact_match != NOTHING) {
  405.     return exact_match;
  406.     } else {
  407.     switch (match_count) {
  408.       case 0:
  409.         return NOTHING;
  410.       case 1:
  411.         return last_match;
  412.       default:
  413.         return AMBIGUOUS;
  414.     }
  415.     }
  416. }
  417.  
  418. /* use this if you don't care about ambiguity */
  419. dbref last_match_result()
  420. {
  421.     if (exact_match != NOTHING) {
  422.     return exact_match;
  423.     } else {
  424.     return last_match;
  425.     }
  426. }
  427.  
  428. dbref noisy_match_result()
  429. {
  430.     dbref match;
  431.     switch (match = match_result()) {
  432.       case NOTHING:
  433.     notify(match_who, nomatch_message);
  434.     return NOTHING;
  435.       case AMBIGUOUS:
  436.     notify(match_who, ambiguous_message);
  437.     return NOTHING;
  438.       default:
  439.     return match;
  440.     }
  441. }
  442.  
  443. dbref match_controlled(player, name)
  444.      dbref player;
  445.      const char *name;
  446. {
  447.     dbref match;
  448.     init_match(player, name, NOTYPE);
  449.     match_everything();
  450.     
  451.     match = noisy_match_result();
  452.     if (match != NOTHING && !controls(player, match)) {
  453.     notify(player, "Permission denied.");
  454.     return NOTHING;
  455.     } else {
  456.     return match;
  457.     }
  458. }
  459.  
  460.